#!/bin/bash

set -e
set -o pipefail

PROJDIR=$(dirname $(cd $(dirname ${0}); pwd -P))

# {{{ Help message
function help() {
  cat >&2 << EOF
This script is a driver for "runtime tests".
The "runtime test" is to test gosseract package in specific environments,
such as OS, Go version and Tesseract version.

Options:
  --driver|-d {name}  Specify VM driver software, either of [docker, vagrant].
  --build|-b          Build testable images if provided, otherwise pull images.
  --push|-p           Push local images to dockerhub (for development purpose).
  --quiet|-q          Don't show verbose logs of setting VMs up.
  --run|-R {case}     Run only cases which have specified pattern in the case names.
  --exclude|-X {case} Run only cases which DON'T have specified pattern in the case names.
  --rm                Remove VMs which are created by this runtime test.
  --help|-h           Show this message ;)

Examples:

  ./test/runtime -d docker -v --run CentOS --rm

EOF
}
# }}}

# {{{ Parse CLI options
function parse_options() {
  DRIVER=
  REMOVE=
  BUILD=
  PUSH=
  QUIET=
  MATCH=
  EXCLUDE=
  while [[ $# -gt 0 ]]; do
  case "${1}" in
      --driver|-d)
      DRIVER="${2}"
      shift && shift
      ;;
      --rm)
      REMOVE=YES
      shift
      ;;
      --build|-b)
      BUILD=YES
      shift
      ;;
      --push|-p)
      PUSH=YES
      shift
      ;;
      --quiet|-q)
      QUIET="--quiet"
      shift
      ;;
      --run|-R)
      MATCH="${2}"
      shift && shift
      ;;
      --exclude|-X)
      EXCLUDE="${2}"
      shift && shift
      ;;
      --help|-h)
      help && exit 0
      ;;
      *)
      printf "Unkown flag: ${1}\n\n"
      help
      exit 1
      ;;
  esac
  done
}
# }}}

# {{{ Runner function for "--driver docker"
function test_docker_runtimes() {
  for runtime in `ls ${PROJDIR}/test/runtimes/*.Dockerfile`; do
    testcase=`basename ${runtime} | sed -e s/\.Dockerfile$//`
    if [ -n "${MATCH}" ]; then
      if [[ "${testcase}" != *${MATCH}* ]]; then
        continue
      fi
    fi
    if [ -n "${EXCLUDE}" ]; then
      if [[ "${testcase}" == *${EXCLUDE}* ]]; then
        continue
      fi
    fi
    echo "┌───────────── ${testcase}"
    if [ -n "${BUILD}" ]; then
      echo "│ [Docker] Building image..."
      docker build . -f ${runtime} -t gosseract/test:${testcase} ${QUIET} | sed "s/^/│ /"
    else
      echo "│ [Docker] Pulling image..."
      docker pull gosseract/test:${testcase} | sed "s/^/│ /"
    fi
    echo "│ [Docker] Running tests..."
    docker run -i -t --rm gosseract/test:${testcase} | sed "s/^/│ [${testcase}] /"
    if [ -n "${PUSH}" ]; then
      echo "│ [Docker] Pushing the image..."
      docker push gosseract/test:${testcase} | sed "s/^/│ /"
    fi
    if [ -n "${REMOVE}" ]; then
      echo "│ [Docker] Removing image..."
      docker rmi gosseract/test:${testcase} 1>/dev/null
    fi
    echo "└───────────── ${testcase} [OK]"
  done
}
# }}}

# {{{ Runner function for "--driver vagrant"
function test_vagrant_runtimes() {
  for runtime in `ls ${PROJDIR}/test/runtimes/*.Vagrantfile`; do
    testcase=`basename ${runtime} | sed -e s/\.Vagrantfile$//`
    if [ -n "${MATCH}" ]; then
      if [[ "${testcase}" != *${MATCH}* ]]; then continue; fi
    fi
    echo "┌───────────── ${testcase}"
    echo "│ [Vagrant] Making VM up..."
    vboxname=gosseract-test-${testcase}
    VAGRANT_VAGRANTFILE=${runtime} VIRTUALBOX_NAME=${vboxname} vagrant up --provider virtualbox | sed "s/^/│ /"
    VAGRANT_VAGRANTFILE=${runtime} VIRTUALBOX_NAME=${vboxname} vagrant provision | sed "s/^/│ /"
    VAGRANT_VAGRANTFILE=${runtime} vagrant halt | sed "s/^/│ /"
    if [ -n "${REMOVE}" ]; then
      echo "│ [Vagrant] Removing VM..."
      VAGRANT_VAGRANTFILE=${runtime} vagrant destroy -f | sed "s/^/│ /"
    fi
    echo "└───────────── ${testcase} [OK]"
  done
}
# }}}

# {{{ Main procedure
function __main__() {
  parse_options $@
  case ${DRIVER} in
    docker)
    test_docker_runtimes
    ;;
    vagrant)
    test_vagrant_runtimes
    ;;
    *)
    test_docker_runtimes
    test_vagrant_runtimes
    ;;
  esac
}
# }}}

# Entrypoint
__main__ $@
